﻿using System;
using System.Threading.Tasks;
using K9Nano.Application;
using K9Nano.Domain;
using Microsoft.AspNetCore.Mvc;

namespace K9Nano.AspNetCore.Api
{
    public abstract class CurdController<TCurdAppService, TEntity, TCreateDto, TEditDto, TItemDto, TPagedInputDto, TKey> : ControllerBase
        where TCurdAppService : ICurdApplicationService<TEntity, TCreateDto, TEditDto, TItemDto, TPagedInputDto, TKey>
        where TEntity : class, IEntity<TKey>
        where TCreateDto : IDto<TKey>
        where TEditDto : IDto<TKey>
        where TItemDto : IDto<TKey>
        where TPagedInputDto : IPagedInputDto<TEntity>
        where TKey : IEquatable<TKey>
    {
        protected readonly TCurdAppService CurdAppService;

        protected CurdController(TCurdAppService curdAppService)
        {
            CurdAppService = curdAppService;
        }

        [HttpPost]
        public virtual async Task<TItemDto> Create(TCreateDto dto)
        {
            var result = await CurdAppService.CreateAsync(dto, HttpContext.RequestAborted);
            return result;
        }

        [HttpPut]
        public virtual async Task<TItemDto> Update(TEditDto dto)
        {
            var result = await CurdAppService.UpdateAsync(dto, HttpContext.RequestAborted);
            return result;
        }

        [HttpGet]
        public virtual async Task<PagedResultDto<TItemDto>> List([FromQuery]TPagedInputDto dto)
        {
            var result = await CurdAppService.ListAsync(dto, HttpContext.RequestAborted);
            return result;
        }

        [HttpDelete]
        public virtual async Task Delete(TKey id)
        {
            await CurdAppService.DeleteAsync(id, HttpContext.RequestAborted);
        }

        [HttpGet]
        public virtual async Task<TItemDto> Get(TKey id)
        {
            var result = await CurdAppService.GetAsync(id, HttpContext.RequestAborted);
            return result;
        }
    }

    public abstract class CurdController<TEntity, TCreateDto, TEditDto, TItemDto, TPagedInputDto, TKey>
        : CurdController<CurdApplicationService<TEntity, TCreateDto, TEditDto, TItemDto, TPagedInputDto, TKey>, TEntity, TCreateDto, TEditDto, TItemDto, TPagedInputDto, TKey>
        where TEntity : class, IEntity<TKey>
        where TCreateDto : IDto<TKey>
        where TEditDto : IDto<TKey>
        where TItemDto : IDto<TKey>
        where TPagedInputDto : IPagedInputDto<TEntity>
        where TKey : IEquatable<TKey>
    {
        protected CurdController(CurdApplicationService<TEntity, TCreateDto, TEditDto, TItemDto, TPagedInputDto, TKey> curdAppService) : base(curdAppService)
        {
        }
    }
}